package com.mini.mybatis.reflection.factory;

import java.lang.reflect.Constructor;
import java.util.*;

/**
 * 默认对象工厂实现
 */
public class DefaultObjectFactory implements ObjectFactory {
    
    @Override
    public void setProperties(Properties properties) {
        // 默认实现不需要额外配置
    }
    
    @Override
    public <T> T create(Class<T> type) {
        return create(type, null, null);
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        Class<?> classToCreate = resolveInterface(type);
        return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
    }
    
    @Override
    public <T> boolean isCollection(Class<T> type) {
        return Collection.class.isAssignableFrom(type);
    }
    
    /**
     * 解析接口类型，返回具体的实现类
     */
    protected Class<?> resolveInterface(Class<?> type) {
        Class<?> classToCreate;
        if (type == List.class || type == Collection.class || type == Iterable.class) {
            classToCreate = ArrayList.class;
        } else if (type == Map.class) {
            classToCreate = HashMap.class;
        } else if (type == SortedSet.class) {
            classToCreate = TreeSet.class;
        } else if (type == Set.class) {
            classToCreate = HashSet.class;
        } else {
            classToCreate = type;
        }
        return classToCreate;
    }
    
    /**
     * 实例化类
     */
    @SuppressWarnings("unchecked")
    private <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        try {
            Constructor<T> constructor;
            if (constructorArgTypes == null || constructorArgs == null) {
                constructor = type.getDeclaredConstructor();
            } else {
                constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[0]));
            }
            
            try {
                return constructor.newInstance(constructorArgs == null ? null : constructorArgs.toArray(new Object[0]));
            } catch (IllegalAccessException e) {
                if (Reflector.canControlMemberAccessible()) {
                    constructor.setAccessible(true);
                    return constructor.newInstance(constructorArgs == null ? null : constructorArgs.toArray(new Object[0]));
                } else {
                    throw e;
                }
            }
        } catch (Exception e) {
            String argTypes = Optional.ofNullable(constructorArgTypes).orElseGet(Collections::emptyList)
                .stream().map(Class::getSimpleName).reduce((o1, o2) -> o1 + "," + o2).orElse("");
            String argValues = Optional.ofNullable(constructorArgs).orElseGet(Collections::emptyList)
                .stream().map(String::valueOf).reduce((o1, o2) -> o1 + "," + o2).orElse("");
            throw new RuntimeException("创建类型 " + type + " 的实例时出错。原因: " + e.toString() + 
                ". 构造器: " + argTypes + ". 参数: " + argValues, e);
        }
    }
    
    /**
     * 简化版反射器
     */
    private static class Reflector {
        public static boolean canControlMemberAccessible() {
            try {
                SecurityManager securityManager = System.getSecurityManager();
                if (null != securityManager) {
                    securityManager.checkPermission(new RuntimePermission("accessDeclaredMembers"));
                }
                return true;
            } catch (SecurityException e) {
                return false;
            }
        }
    }
}